#ifndef _HTTP_CMD_HPP_20120714
#define _HTTP_CMD_HPP_20120714

#include "base.hpp"

#include "cmd_comm.hpp"
#include "cmd_value.hpp"
#include "cmd_type.hpp"
#include "cmd_err_code.hpp"

namespace cmd
{
	typedef std::map<std::string, std::string> KeyValMap;
	typedef KeyValMap::iterator KeyValMap_Iter;
	typedef KeyValMap::const_iterator KeyValMap_CIter;

	enum PlatformType
	{
		P_UNKNOWN                 = 0,
		P_TENCENT_GET_USER_INFO   = 1,
	};

	inline const char * platform_type_2_str(uint16_t type)
	{
		switch (type)
		{
			case P_UNKNOWN:
				return "P_UNKNOWN";
			case P_TENCENT_GET_USER_INFO:
				return "user/get_info";

			default:
				break;
		}

		return "P_UNKNOWN";
	}

	template <cmd_0_type cmd_0, cmd_1_type cmd_1>
	class PlatformCmdTmpl : public SSHead
	{
		public :
			uint16_t   _err_code;
			// PlatformType
			uint16_t   _type;
			uint32_t   _sequence;
			KeyValMap  _key_val_map;

		public :
			PlatformCmdTmpl()
				: SSHead(cmd_0, cmd_1),
				  _err_code(0),
				  _sequence(0)
			{
			}

			uint32_t size() const
			{
				uint32_t ret = sizeof(_sequence);
				ret         += sizeof(uint32_t);
				for (KeyValMap_Iter iter = _key_val_map.begin(); \
						iter != _key_val_map.end(); ++ iter)
				{
					ret += str_sizeof(iter->first);
					ret += str_sizeof(iter->second);
				}

				return ret;
			}

			const std::string to_string() const
			{
				std::ostringstream oss;
				oss << " body: {err_code: " << (int) _err_code
					<< "(" << game_err_to_str(_err_code) << ")"
					<< ", type: " << _type
					<< ", sequence: " << _sequence
					<< ", map: {size:" << _key_val_map.size() << "}{";

				KeyValMap_CIter iter = _key_val_map.begin();
				for (; iter != _key_val_map.end(); ++ iter)
				{
					oss << "(" << iter->first << ", " << iter->second << ")";
				}

				oss << "}}";

				return oss.str();
			}

			void serialize(Streamer & streamer)
			{
				SSHead::serialize(streamer);
				streamer & _err_code
					     & _type
						 & _sequence;
				if (0 != _err_code)
				{
					return;
				}

				uint32_t sz = _key_val_map.size();

				streamer & sz;

				if (streamer.in())
				{
					KeyValMap_Iter iter = _key_val_map.begin();
					for (; iter != _key_val_map.end(); ++ iter)
					{
						streamer & iter->first
							     & iter->second;
					}
				}
				else
				{
					std::string key;
					std::string val;
					for (uint32_t i = 0; i < sz; ++ i)
					{
						streamer & key
							     & val;
						_key_val_map.insert(std::make_pair(key, val));
					}
				}
			}
	};

	typedef PlatformCmdTmpl<HTTP_CLIENT_CMD_0, SS_TENCENT_PLAT_REQ> SSTencentPlatReq;
	typedef PlatformCmdTmpl<HTTP_CLIENT_CMD_0, SS_TENCENT_PLAT_RES> SSTencentPlatRes;
};

#endif

